﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Windows.Media;
using System.Windows.Forms;
using Styx;
using Styx.Helpers;
using Styx.Common;
using Styx.CommonBot.POI;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System.Runtime.InteropServices;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;

namespace BeastMaster
{
    public partial class Classname : CombatRoutine
    {
        public float MeleeRange = 3.5f;

        #region spellID

        public int Misdirection = 34477;
        public int SerpentSting = 1978;
        public int SerpentStingAura = 118253;
        public int ExplosiveShot = 53301;
        public int CobraShot = 77767;
        public int ArcaneShot = 3044;
        public int MultiShot = 2643;
        public int KillShot = 53351;
        public int BlackArrow = 3674;
        public int MurderOfCrows = 131894;
        public int SilencingShot = 34490;
        public int FeignDeath = 5384;
        public int RapidFire = 3045;
        public int Disengage = 781;
        public int Deterrence = 19263;
        public int ConcussiveShot = 5116;
        public int TrapLauncher = 77769;
        public int FreezingTrap = 60192;
        public int ExplosiveTrap = 82939;
        public int SnakeTrap = 82948;
        public int IceTrap = 82941;
        public int StoneForm = 20894;
        public int Camouflage = 51753;
        
        public int MendPet = 136;
        public int MastersCall = 53271;
        public int HuntersMark = 1130;
        public int Flare = 1543;
        public int Readiness = 23989;
        public int Stampede = 121818;
        public int DireBeast = 120679;
        public int AspectIronHawk = 109260;
        public int GlaiveToss = 117050;
        public int ScatterShot = 19503;
        public int WidowVenom = 82654;
        public int TranquilizingShot = 19801;
        public int LockAndLoad = 56343;
        public int BloodFury = 20572;
        public int Berserking = 26297;
        public int BestialWrath = 19574;
        public int KillCommand = 34026;
        public int FocusFire = 82692;
        public int Frenzy = 19615;
        public int LynxRush = 120697;
        public int BlinkStrike = 130392;
        public int SteadyShot = 56641;
        public int Lifeblood = 121279;
        public int GiftOfTheNaruu = 59544;

        #endregion SpellID

        #region spell msgs
        public string HavePotionBuff = "";
        public string HaveFlaskBuff = "";
        public string HaveHealPotions = "";
        public string HaveLifeSpirit = "";
        public string HaveHealthStone = "";
        public string LastSpell = "";
        #endregion spellmsgs

        #region facing
        public void FacingTarget()
        {
            if (gotTarget
                && !BeastMasterSettings.myPrefs.Facing
                && !Me.IsSafelyFacing(Me.CurrentTarget))
            {
                Me.CurrentTarget.Face();
            }
            return;
        }
         
        #endregion facing

        #region Movement
        public void MoveInRange(float dist)
        {
            if (StyxWoW.Me.Location.Distance(StyxWoW.Me.CurrentTarget.Location) > dist)
            {
                while (StyxWoW.Me.Location.Distance(StyxWoW.Me.CurrentTarget.Location) > dist)
                {
                    Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
                };
            }
            Navigator.PlayerMover.MoveStop();
        }
        #endregion movement

        #region needmisdirection
        public bool NeedMisdirection()
        {
            if (gotTarget
                 && BeastMasterSettings.myPrefs.misdirection == 1
                 && !buffExists(Misdirection, Me)
                 && Me.CurrentTarget.ThreatInfo.RawPercent > 75
                 && !spellOnCooldown(Misdirection))
            {
                Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                return true;
            }
            return false;
        }
        #endregion needmisdirection

        #region GetAsyncKeyState

        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        #endregion

        #region pause

        public bool PauseAoe = false;
        public bool Paused = false;

        public override void ShutDown()
        {
            Lua.Events.DetachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
        }

        private void HandleModifierStateChanged(object sender, LuaEventArgs args)
        {
            if (BeastMasterSettings.myPrefs.PauseCRKeys == BeastMasterSettings.Keypress.None
                && BeastMasterSettings.myPrefs.AoePauseKeys == BeastMasterSettings.Keypress.None)
            {
                return;
            }

            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == BeastMasterSettings.myPrefs.AoePauseKeys.ToString())
                {
                    PauseAoe = !PauseAoe;
                    if (PauseAoe)
                    {
                        Logging.Write("Aoe turned off, press {0} in WOW again to turn back on",
                                     BeastMasterSettings.myPrefs.AoePauseKeys.ToString());
                        if (BeastMasterSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Aoe Turned off\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("Turning Aoe back on");
                        if (BeastMasterSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Aoe turned on\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == BeastMasterSettings.myPrefs.PauseCRKeys.ToString())
                {
                    Paused = !Paused;
                    if (Paused)
                    {
                        Logging.Write("BeastMaster paused, press {0} in WOW again to turn back on",
                                     BeastMasterSettings.myPrefs.PauseCRKeys.ToString());
                        if (BeastMasterSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"BeastMaster Paused\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("BeastMaster running again ....");
                        if (BeastMasterSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"BeastMaster running again ....\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
        }

        Composite PauseCR()
        {
            return
                new Decorator(ret => Paused,
                    new Action(ret =>
                    {
                        return;
                    }
            ));
        }
        Composite PauseAOE()
        {
            return
                new Decorator(ret => PauseAoe,
                    new Action(ret =>
                    {
                        return;
                    }
            ));
        }
        #endregion pause

        #region logs
        public void LogMsg(string msg, int kleurtje)
        {
            Color kleur = Colors.Yellow;
            switch (kleurtje)
            {
                case 0:
                    kleur = Colors.Orange;
                    break;
                case 1:
                    kleur = Colors.PaleGreen;
                    break;
                case 2:
                    kleur = Colors.BlanchedAlmond;
                    break;
                case 3:
                    kleur = Colors.Yellow;
                    break;
                case 4:
                    kleur = Colors.Red;
                    break;
                case 5:
                    kleur = Colors.LightBlue;
                    break;
                case 6:
                    kleur = Colors.Crimson;
                    break;
                case 7:
                    kleur = Colors.Cyan;
                    break;
                case 8:
                    kleur = Colors.DarkSeaGreen; // TotH
                    break;
                case 9:
                    kleur = Colors.Honeydew; //Lock and load
                    break;
                case 10:
                    kleur = Colors.DeepSkyBlue; //focusdump
                    break;
            }
            Logging.Write(kleur, msg);
        }
        #endregion logs

        #region AddCounting
        private int addCount
        {
            get
            {
                int count = 0;
                foreach (WoWUnit u in ObjectManager.GetObjectsOfType<WoWUnit>(true, true))
                {
                    if (gotTarget
                        && u.CanSelect
                        && !u.IsPlayer
                        && u.IsAlive
                        && u.Guid != Me.Guid
                        && !u.IsFriendly
                        && u.IsHostile
                        && u.Attackable
                        && !u.IsTotem
                        && !u.IsCritter
                        && !u.IsNonCombatPet
                        && (u.Location.Distance(Me.CurrentTarget.Location) <= 10 || u.Location.Distance2D(Me.CurrentTarget.Location) <= 10))
                    {
                        count++;
                    }
                }
                return count;
            }
        }
        #endregion AddCounting

        #region Kind of target
        public bool IsBoss
        {
            get
            {
                if (Me.CurrentTarget != null
                    && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.WorldBoss)
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && target.IsBoss(Me.CurrentTarget))
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && Me.CurrentTarget.MaxHealth >= (65 * 1000000))
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.RareElite
                    && Me.CurrentTarget.MaxHealth >= (Me.MaxHealth * BeastMasterSettings.myPrefs.ElitesHealth)
                    && !Me.GroupInfo.IsInParty
                    && !Me.IsInInstance
                    && !Me.GroupInfo.IsInRaid)
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                         && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Rare
                         && Me.CurrentTarget.MaxHealth >= (Me.MaxHealth * BeastMasterSettings.myPrefs.ElitesHealth)
                         && !Me.GroupInfo.IsInParty
                         && !Me.IsInInstance
                         && !Me.GroupInfo.IsInRaid)
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Elite
                    && Me.CurrentTarget.MaxHealth >= (Me.MaxHealth * BeastMasterSettings.myPrefs.ElitesHealth)
                    && !Me.GroupInfo.IsInParty
                    && !Me.IsInInstance
                    && !Me.GroupInfo.IsInRaid)
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && Me.CurrentTarget.Name.Contains("Training Dummy")
                    && !Me.IsInInstance)
                {
                    return true;
                }
                else if (Me.CurrentTarget != null
                    && Me.CurrentTarget.IsPlayer
                    && !Me.CurrentTarget.IsFriendly)
                {
                    return true;
                }
                return false;
            }
        }

        #endregion Kind of Target

        #region trinkets + flasks
        public bool FlaskBuff()
        {
            if (Me.HasAura("Flask of the Warm Sun")) { return true; }
            if (Me.HasAura("Flask of Winter's Bite")) { return true; }
            if (Me.HasAura("Flask of the Earth")) { return true; }
            if (Me.HasAura("Flask of Spring Blossoms")) { return true; }
            if (Me.HasAura("Flask of Falling Leaves")) { return true; }
            return false;
        }
        public void AlchemistFlask()
        {
            if (BeastMasterSettings.myPrefs.alchemyflask == 1)
            {

                if (!Me.HasAura("Enhanced Agility") && !FlaskBuff() && !Me.Mounted)
                {
                    WoWItem alchflask = Me.BagItems.FirstOrDefault(h => h.Entry == 76089);
                     
                        if (alchflask != null)
                        {
                            alchflask.Use();
                            Logging.Write(Colors.LightBlue, "Using Alchemist's Flask");
                        }
                    
                }
            }
        }
        public void myPotion()
        {
            if (Me.CurrentTarget != null
                && Me.Combat
                && (BeastMasterSettings.myPrefs.virmenpotion == 1
                && Me.IsInInstance)
                || (BeastMasterSettings.myPrefs.virmenpotion == 2
                && Me.GroupInfo.IsInRaid))
            {
                WoWItem potion = Me.BagItems.FirstOrDefault(h => h.Entry == 76089);

                if (potion == null
                    && HavePotionBuff != "no")
                {
                    Logging.Write(Colors.BlanchedAlmond, "I have no Agility Potion");
                    HavePotionBuff = "no";
                }
                if (potion != null && potion.CooldownTimeLeft.TotalMilliseconds <= 0)
                {
                    potion.Use();
                    Logging.Write(Colors.BlanchedAlmond, "Using Agility Potion");
                    HavePotionBuff = "yes";
                }
            }
            return;
        }
        public void HealthStone()
        {
            if (Me.Combat
                && Me.HealthPercent <= BeastMasterSettings.myPrefs.healthstonepercent)
            {
                WoWItem hstone = Me.BagItems.FirstOrDefault(h => h.Entry == 5512);
                if (hstone == null
                    && HaveHealthStone != "no")
                {
                    Logging.Write(Colors.BlanchedAlmond, "I have no Healthstone");
                    HaveHealthStone = "no";
                }
                if (hstone != null && hstone.CooldownTimeLeft.TotalMilliseconds <= 0)
                {
                    hstone.Use();
                    Logging.Write(Colors.BlanchedAlmond, "Using Healthstone");
                    HaveHealthStone = "yes";
                }
            }
            return;
        }
        public void myFlask()
        {
            bool useFlask = false;

            if ((BeastMasterSettings.myPrefs.agilityflask == 1
                && Me.IsInInstance)
                || (BeastMasterSettings.myPrefs.agilityflask == 2
                && Me.GroupInfo.IsInRaid))
            { 
                useFlask = true; 
            }

            if (Me.Combat
                && useFlask
                && !FlaskBuff())
            {
                WoWItem flask = Me.BagItems.FirstOrDefault(h => h.Entry == 76084);
                if (flask == null
                    && HaveFlaskBuff != "no")
                {
                    Logging.Write(Colors.BlanchedAlmond, "I have no Agility Flask");
                    HaveFlaskBuff = "no";
                }
                if (flask != null && flask.CooldownTimeLeft.TotalMilliseconds <= 0)
                {
                    flask.Use();
                    Logging.Write(Colors.BlanchedAlmond, "Using Agility Flask");
                    HaveFlaskBuff = "yes";
                }
            }
            return;
        }
        public void UseTrinket1()
        {
            if (Me.CurrentTarget != null
                && Me.CurrentTarget.IsAlive
                && Me.Combat)
            {

                var firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;
                if (BeastMasterSettings.myPrefs.trinket1 == 2
                    && IsBoss)
                {

                    if (firstTrinket != null && CanUseEquippedItem(firstTrinket))
                    {
                        firstTrinket.Use();
                        //LogMsg("Using 1st trinket", 2);
                    }
                }
                if (BeastMasterSettings.myPrefs.trinket1 == 1)
                {
                    if (firstTrinket != null && CanUseEquippedItem(firstTrinket))
                    {
                        firstTrinket.Use();
                        //LogMsg("Using 1st trinket", 2);
                    }
                }
            }
            return;
        }
        public void UseTrinket2()
        {

            if (Me.CurrentTarget != null
                && Me.CurrentTarget.IsAlive
                && Me.Combat)
            {
                var secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;


                if (BeastMasterSettings.myPrefs.trinket2 == 2
                    && IsBoss)
                {

                    if (secondTrinket != null && CanUseEquippedItem(secondTrinket))
                    {
                        secondTrinket.Use();
                        //LogMsg("Using 2nd trinket", 2);
                    }
                }
                else if (BeastMasterSettings.myPrefs.trinket2 == 1)
                {
                    if (secondTrinket != null && CanUseEquippedItem(secondTrinket))
                    {
                        secondTrinket.Use();
                        //LogMsg("Using 2nd trinket", 2);
                    }
                }
            }
            return;
        }
        public void UseEngiGloves()
        {

            if (Me.CurrentTarget != null
                && Me.CurrentTarget.IsAlive
                && Me.Combat)
            {
                var engiGloves = StyxWoW.Me.Inventory.Equipped.Hands;

                if (BeastMasterSettings.myPrefs.engigloves == 2
                    && IsBoss)
                {
                    if (engiGloves != null && CanUseEquippedItem(engiGloves))
                    {
                        engiGloves.Use();
                        //LogMsg("Using Engineer Gloves", 2);
                    }
                }
                else if (BeastMasterSettings.myPrefs.engigloves == 1)
                {
                    if (engiGloves != null && CanUseEquippedItem(engiGloves))
                    {
                        engiGloves.Use();
                        //LogMsg("Using Engineer Gloves", 2);
                    }
                }
            }
            return;
        }
        private static bool CanUseEquippedItem(WoWItem item)
        {
            // Check for engineering tinkers!
            string itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
                return false;


            return item.Usable && item.Cooldown <= 0;
        }
        #endregion trinkets + flasks

        #region spelcasting
        private delegate T Selection<out T>(object context);
        Composite Cast(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.HasSpell(spell) && SpellManager.CanCast(spell) && IsInRange(35, Me.CurrentTarget),
                    new Action(ret => 
                    {
                        SpellManager.Cast(spell);
                    }
                    ));
        }
        Composite Cast(int spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.HasSpell(spell) && SpellManager.CanCast(spell) && IsInRange(35, Me.CurrentTarget),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        lastCast = spell;
                    }
                    ));
        }
        Composite CastBuff(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.HasSpell(spell) && SpellManager.CanCast(spell),
                    new Action(ret =>
                        {
                            SpellManager.Cast(spell, Me);

                        }));
        }
        Composite CastBuff(int spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.HasSpell(spell) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell, Me);
                        lastCast = spell;
                    }));
        }
        #endregion spellcasting

        #region Buff Checks

        public bool buffExists(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return true;
            }
            return false;
        }

        public double buffTimeLeft(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                {
                    if (Results.TimeLeft.TotalMilliseconds > 0)
                        return Results.TimeLeft.TotalMilliseconds;
                }
            }
            return 0;
        }

        public uint buffStackCount(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return Results.StackCount;
            }
            return 0;
        }
        #endregion

        #region Cache Checks
        public IEnumerable<WoWAura> cachedAuras = new List<WoWAura>();
        public IEnumerable<WoWAura> cachedTargetAuras = new List<WoWAura>();
        public void getCachedAuras()
        {
            if (Me.CurrentTarget != null)
                cachedTargetAuras = Me.CurrentTarget.GetAllAuras();
            cachedAuras = Me.GetAllAuras();
        }
        #endregion

        #region Cooldown Checks
        private Dictionary<WoWSpell, long> Cooldowns = new Dictionary<WoWSpell, long>();
        public TimeSpan cooldownLeft(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.CooldownTimeLeft;
                    return TimeSpan.MaxValue;
                }
            }
            return TimeSpan.MaxValue;
        }
        long lastUsed;
        public int lastCast;
        public bool onCooldown(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.Cooldown;
                    return false;
                }
            }
            return false;
        }
        public TimeSpan spellCooldownLeft(int Spell, bool useTracker = false)
        {
            if (useTracker)
                return cooldownLeft(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Override.CooldownTimeLeft;
            }
            return TimeSpan.MaxValue;
        }
        public bool spellOnCooldown(int Spell, bool useTracker = false)
        {
            if (useTracker)
                return !onCooldown(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
                return results.Override != null ? results.Override.Cooldown : results.Original.Cooldown;
            return false;
        }
        #endregion

        #region Debuff Checks

        public bool debuffExists(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a => a.SpellId == Debuff && a.CreatorGuid == Me.Guid);
                if (aura != null)
                {
                    return true;
                }
            }
            return false;
        }

        public double debuffTimeLeft(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.SpellId == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
            return 0;
        }

        public uint debuffStackCount(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.SpellId == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
            return 0;
        }
        #endregion

        #region Focus checks
        public double Focus
        {
            get
            {
                try
                {
                    using (StyxWoW.Memory.AcquireFrame())
                    {
                        return Styx.WoWInternals.Lua.GetReturnVal<int>("return UnitPower(\"player\");", 0);
                    }
                }
                catch { return 0; }
            }
        }
        #endregion

        #region Macro Checks
        public bool Manual { get { return Convert.ToBoolean(Lua.GetReturnVal<int>("return Manual and 0 or 1", 0)); } }
        public bool useCDs { get { return Convert.ToBoolean(Lua.GetReturnVal<int>("return useCDs and 0 or 1", 0)); } }
        #endregion

        #region Target Checks
        internal IEnumerable<WoWUnit> attackableTargets
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(U => U.Attackable && U.CanSelect && !U.IsFriendly && !U.IsDead && !U.IsNonCombatPet && !U.IsCritter); }
        }
        public bool gotTarget { get { return Me.GotTarget && Me.CurrentTarget != null && Me.CurrentTarget.Attackable && (!Me.CurrentTarget.IsDead && !Me.CurrentTarget.IsFriendly || isTargetDummy); } }
        public bool isTargetDummy { get { return Me.CurrentTarget.Name == "Training Dummy" || Me.CurrentTarget.Name == "Raider's Training Dummy"; } }
        internal IEnumerable<WoWUnit> nearbyTargets(WoWPoint fromLocation, double Radius)
        {
            var Hostile = attackableTargets;
            var maxDistance = Radius * Radius;
            return Hostile.Where(x => x.Location.DistanceSqr(fromLocation) < maxDistance);
        }
        public double targetDistance(WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.DistanceSqr;
                if (Results != null)
                    return onTarget.DistanceSqr;
            }
            return 0;
        }
        public double targetHP(WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.HealthPercent;
                if (Results != null)
                    return onTarget.HealthPercent;
            }
            return 0;
        }
        #endregion

        #region Timer Checks
        private int conv_Date2Timestam(DateTime _time)
        {
            var date1 = new DateTime(1970, 1, 1);
            DateTime date2 = _time;
            var ts = new TimeSpan(date2.Ticks - date1.Ticks);
            return (Convert.ToInt32(ts.TotalSeconds));
        }
        private uint current_life;
        private int current_time;
        private ulong guid;
        private uint first_life;
        private uint first_life_max;
        private int first_time;
        public long targetExistence(WoWUnit onTarget)
        {
            if (onTarget == null) return 0;
            if (isTargetDummy) return 9999;
            if (onTarget.CurrentHealth == 0 || onTarget.IsDead || !onTarget.IsValid || !onTarget.IsAlive)
                return 0;
            if (guid != onTarget.Guid)
            {
                guid = onTarget.Guid;
                first_life = onTarget.CurrentHealth;
                first_life_max = onTarget.MaxHealth;
                first_time = conv_Date2Timestam(DateTime.Now);
            }
            current_life = onTarget.CurrentHealth;
            current_time = conv_Date2Timestam(DateTime.Now);
            var time_diff = current_time - first_time;
            var hp_diff = first_life - current_life;
            if (hp_diff > 0)
            {
                var full_time = time_diff * first_life_max / hp_diff;
                var past_first_time = (first_life_max - first_life) * time_diff / hp_diff;
                var calc_time = first_time - past_first_time + full_time - current_time;
                if (calc_time < 1) calc_time = 99;
                var time_to_die = calc_time;
                var fight_length = full_time;
                return time_to_die;
            }
            if (hp_diff < 0)
            {
                guid = onTarget.Guid;
                first_life = onTarget.CurrentHealth;
                first_life_max = onTarget.MaxHealth;
                first_time = conv_Date2Timestam(DateTime.Now);
                return -1;
            }
            if (current_life == first_life_max)
                return 9999;
            return -1;
        }
        #endregion

        #region Pet
         
        public bool TakePetsTarget()
        {
            if (!BeastMasterSettings.myPrefs.Targeting
                && (Me.Pet.Aggro
                || Me.PetInCombat)
                && !Me.GotTarget)
            { 
                return true;
            }
            return false;
        }
        string laatsteSpellCast = "nothing";
        Stopwatch petPresenceTimer = new Stopwatch();

        public void CheckPet()
        {
            if (laatsteSpellCast == "CallPet"
                && Me.Pet != null
                && Me.GotAlivePet)
            {
                laatsteSpellCast = "nothing";
            }
            return;
        }
        public void CallPet()
        {

            if (BeastMasterSettings.myPrefs.autocallrevivepet == 1)
            {
                StyxWoW.SleepForLagDuration();
                string myPet = "Call Pet " + BeastMasterSettings.myPrefs.callpetnr;
                if (Me.Pet == null
                    && !Me.Mounted
                    && !Me.IsFlying
                    && !Me.InVehicle
                    && !Me.IsOnTransport
                    && !Me.OnTaxi
                    && laatsteSpellCast != "CallPet")
                {
                    if (SpellManager.CanCast(myPet))
                    {
                        SpellManager.Cast(myPet);
                        petPresenceTimer.Restart();
                        Logging.Write(Colors.PaleGreen, myPet);
                        laatsteSpellCast = "CallPet";
                    }
                }
            }
            return;
        }
        public void RevivePet()
        {
            if (BeastMasterSettings.myPrefs.autocallrevivepet == 1)
            {
                string myPet = "Call Pet " + BeastMasterSettings.myPrefs.callpetnr;
                if (Me.Pet == null
                    && petPresenceTimer.ElapsedMilliseconds >= 2000
                    && !Me.Mounted
                    && !Me.IsFlying
                    && !Me.InVehicle
                    && !Me.IsOnTransport
                    && !Me.OnTaxi)
                {
                    if (SpellManager.CanCast("Revive Pet"))
                    {
                        SpellManager.Cast("Revive Pet");
                        Logging.Write(Colors.PaleGreen, "Revive Pet");
                        petPresenceTimer.Stop();
                        laatsteSpellCast = "RevivePet";
                    }
                }
            }
            return;
        }
        public void ReviveDeadPet()
        {
            string myPet = "Call Pet " + BeastMasterSettings.myPrefs.callpetnr;
            if (Me.Pet != null
                && Me.Pet.IsDead
                && BeastMasterSettings.myPrefs.autocallrevivepet == 1
                && !Me.Mounted
                && !Me.IsFlying)
            {
                SpellManager.Cast("Revive Pet");
                Logging.Write(Colors.PaleGreen, "Revive Pet");
                petPresenceTimer.Stop();
                laatsteSpellCast = "RevivePet";
            }
            return;
        }

        #endregion pet

        #region isinrange
        public bool IsInRange(float range, WoWUnit target)
        { 
                if (StyxWoW.Me.Location.Distance(StyxWoW.Me.CurrentTarget.Location) <= range)
                {
                    return true;
                }
                return false;
        }
        #endregion petisinrange

        #region petisinrange
        public bool PetIsInRange(float range, WoWUnit target)
        {
            if (StyxWoW.Me.Pet.Location.Distance(StyxWoW.Me.Pet.CurrentTarget.Location) <= range)
            {
                return true;
            }
            return false;
        }
        #endregion petisinrange

    }
}






